package main

import (
	"fmt"
	"reflect"
)

var functionRegistry = make(map[string]interface{})

func RegisterFunction(name string, fn interface{}) {
	functionRegistry[name] = fn
}

func Dispatcher(name string) func(...interface{}) []interface{} {
	fn, ok := functionRegistry[name]
	if !ok {
		// 处理函数不存在的情况
		return func(args ...interface{}) []interface{} {
			return []interface{}{"Function not found"}
		}
	}

	fnType := reflect.TypeOf(fn)
	if fnType.Kind() != reflect.Func {
		// 处理不是函数类型的情况
		return func(args ...interface{}) []interface{} {
			return []interface{}{"Invalid function type"}
		}
	}

	// 创建调度函数
	dispatchFunc := func(args ...interface{}) []interface{} {
		if len(args) != fnType.NumIn() {
			// 处理参数数量不匹配的情况
			return []interface{}{"Invalid number of arguments"}
		}

		inputs := make([]reflect.Value, len(args))
		for i := 0; i < len(args); i++ {
			argValue := reflect.ValueOf(args[i])
			argType := fnType.In(i)

			// 检查参数类型是否匹配
			if !argValue.Type().ConvertibleTo(argType) {
				// 处理参数类型不匹配的情况
				return []interface{}{"Invalid argument type"}
			}

			// 转换参数类型
			inputs[i] = argValue.Convert(argType)
		}

		// 调用函数实现
		result := reflect.ValueOf(fn).Call(inputs)

		// 将结果转换为接口切片
		outputs := make([]interface{}, len(result))
		for i, res := range result {
			outputs[i] = res.Interface()
		}

		// 返回结果
		return outputs
	}

	return dispatchFunc
}
func Add(a, b int) int {
	return a + b
}
func Add2(a, b int, c uint32) int {
	tmp := a + b
	return int(int(tmp) / int(c))
}
func TestFun(a int, s string) (string, error) {
	return fmt.Sprintf("%v______%s", a, s), nil
}
func Subtract(a, b int) int {
	return a - b
}

func main() {
	RegisterFunction("add", Add)
	RegisterFunction("add2", Add2)
	RegisterFunction("TestFun", TestFun)
	RegisterFunction("subtract", Subtract)

	// 创建调度函数
	addFunc := Dispatcher("add")
	add2Func := Dispatcher("add2")
	TestFunFunc := Dispatcher("TestFun")
	subtractFunc := Dispatcher("subtract")

	// 调用函数
	addResult := addFunc(uint32(2), 3)
	fmt.Println(addResult) // Output: [5]

	TestFunResult := TestFunFunc(100, "1000")
	fmt.Println(TestFunResult)

	add2Result := add2Func(12, 13, 2)
	fmt.Println(add2Result)

	subtractResult := subtractFunc(5, 2)
	fmt.Println(subtractResult) // Output: [3]
}
